package org.hnzyx.joggle.starter;


import org.hnzyx.joggle.algorithm.RSAUtil;
import org.hnzyx.joggle.api.ForeignFunction;
import org.hnzyx.joggle.cache.DefaultCacheOperationManager;
import org.hnzyx.joggle.common.URIS;
import org.hnzyx.joggle.config.CustomProperties;
import org.hnzyx.joggle.config.JoggleWebMvcConfigurer;
import org.hnzyx.joggle.config.RedisManager;
import org.hnzyx.joggle.exceptions.SetResponseStatus;
import org.hnzyx.joggle.filter.WebUrlIntercept;
import org.hnzyx.joggle.server.ReplayServer;
import org.hnzyx.joggle.server.SignDetect;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;


/**
 *  思路：
 *  *  用户身份验证通过 生成客户公钥（appkey）密钥(appSecret)，服务端公钥(serverKey)密钥(serverSecret)
 *  *  返回 appkey serverKey
 *  *  用户请求数据 使用appkey加密参数（参数中添加 请求时间 ，serverKey），并且使用参数通过md5获取请求摘要
 *  *  服务端通过appkey 在缓存中获取 appSecret 解密 请求参数 ，并且通过对应的方法生成md5请求摘要（保证数据一致）
 *  *  通过解析出来得请求时间判断重放问题，通过生成的MD5摘要判断数据一致性
 *  *  以上判断都通过了，则使用解析的serverKey 获取对应 serverSecret 对需要返回的数据进行加密
 *
 *
 *  已经实现：
 *  1.get,post请求参数加密 通过认证时候返回RAS公钥accessKey,通过公钥加密参数,请求头带上accessKey
 *  2.sign签名 防止参数篡改 参数字典升序排序 MD5加密
 *  3.重放问题  时间戳+随机数
 *
 * */
@Configuration    //指定这个类是一个配置类
@ConditionalOnWebApplication     //web应用才生效
@EnableConfigurationProperties(value = CustomProperties.class)  //让CustomProperties生效加入到容器中
public class SpringBootStartJoggleApplication {

    /**
     * 获取所有标记JoggelApi注解的方法路径
     * */
    @Bean
    public URIS uris(ConfigurableApplicationContext context){
        // 获取到所有标记 RestController 或者和 Controller 的类
        Map<String, Object> restController = context.getBeansWithAnnotation(RestController.class);
        Map<String, Object> controller = context.getBeansWithAnnotation(Controller.class);
        restController.putAll(controller);
        return new URIS(restController);
    }
    @Bean
    @ConditionalOnBean(URIS.class)
    public WebUrlIntercept webUrlIntercept(){
        return new WebUrlIntercept();
    }

    @Bean
    public DefaultCacheOperationManager defaultCacheOperationManager(){
        return new DefaultCacheOperationManager();
    }

    @Bean
    public RSAUtil rsaUtil(){
        return new RSAUtil();
    }

    @Bean
    public RedisManager redisManager(){
        return new RedisManager();
    }

    @Bean
    public ForeignFunction foreignFunction(){ return new ForeignFunction();}

    @Bean
    public JoggleWebMvcConfigurer joggleWebMvcConfigurer(){
        return new JoggleWebMvcConfigurer();
    }

    @Bean
    public SignDetect signDetect(){
        return new SignDetect();
    }

    @Bean
    public SetResponseStatus setResponseStatus(){
        return new SetResponseStatus();
    }

    @Bean
    public ReplayServer replayServer(){
        return new ReplayServer();
    }

}
